package cn.com.twoke.application.game;

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Objects;
import java.util.function.Consumer;

public class TextureJFrame extends JPanel {

    private final static   BufferedImage tileset;
    private final static   BufferedImage marios;
    private final static   BufferedImage enemies;
    private final static   BufferedImage background1;
    private final static String ROOT_DIR;
    static {
        tileset = loadImage("tileset.png");
        marios = loadImage("marios.png");
        background1 = loadImage("background1.png");
        enemies = loadImage("enemies-bosses.png");
        ROOT_DIR = System.getProperty("user.dir");
    }

    private Consumer<Graphics> handler;
    public TextureJFrame(Consumer<Graphics> handler) {
        this.handler = handler;
    }

    static BufferedImage loadImage(String name) {
        try (InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(name)) {
            BufferedImage image = ImageIO.read(is);
            return image;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }


    static BufferedImage createBufferedImage(int cols, int rows) {
        return new BufferedImage(16 * cols, 16 * rows, BufferedImage.TYPE_INT_ARGB);
    }

   static int WIDTH = 16;
    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        // 获取马里奥的精灵图
        this.handler.accept((Graphics) g);
    }


    private static void outputImage(int cols, int rows, Consumer<Graphics> handler) {
        BufferedImage cache = createBufferedImage(cols, rows);
        handler.accept(cache.getGraphics());
        if (Objects.nonNull(cache)) {
            try {
                BufferedImage bufferedImage = changeColor(cache, new int[]{0x9290FF, 0x00298C},
                        new int[]{0x000000, 0x000000});// 修改颜色为透明);
//                9290FF
                ImageIO.write(bufferedImage, "PNG", new File(ROOT_DIR + File.separator +System.currentTimeMillis()+".png"));
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }



    private static void getPipeAboutBlock(Graphics2D g) {
        for (int i = 0; i < 9; i++) {
            for (int j = 0; j < 4; j++) {
                BufferedImage subimage = tileset.getSubimage(xOfIndex(i), 16 + 17 * 10 + 10 + xOfIndex(j) , 16, 16);
                BufferedImage bufferedImage = changeColor(subimage,
                        new int[]{0x9494FF, 0x00298C},
                        new int[]{0x000000, 0x000000}); // 修改颜色为透明
                g.drawImage(bufferedImage, drawXOfIndex(i), WIDTH * j , WIDTH, WIDTH, null);
           }
        }
    }

    private static void getNormalBlock(Graphics2D g) {
        for (int i = 0; i < 8; i++) {
            for (int j = 0; j < 4; j++) {
                BufferedImage subimage = tileset.getSubimage(xOfIndex(i), 16 + xOfIndex(j), 16, 16);
                BufferedImage bufferedImage = changeColor(subimage,
                        new int[]{0x9494FF, 0x00298C},
                        new int[]{0x00000000, 0x00000000});
                g.drawImage(bufferedImage, drawXOfIndex(i), 16 * j , 16, 16, null);
           }
        }
    }

    private static void getBackground(Graphics2D g) {
        BufferedImage subimage = background1.getSubimage(0, 8, 768, 16 * 15);
        changeColor(subimage,
                new int[]{0x6C6AFF,0x9290FF,0x8886FF},
                new int[]{0x5C94FC,0x5C94FC, 0x5C94FC});
        g.drawImage(subimage, 0, 0, null);
    }

    /**
     * 修改像素点颜色
     * @param image
     * @param sourceColor
     * @param targetColor
     */
    static BufferedImage changeColor(BufferedImage image, int sourceColor[], int targetColor[]) {
        BufferedImage bufferedImage = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_ARGB);
        boolean isTransparency = false;
       for (int x = 0; x < image.getWidth(); x++) {
            for (int y = 0; y < image.getHeight(); y++) {
                int rgb = image.getRGB(x, y);
                isTransparency = false;
                for (int i = 0; i < sourceColor.length; i++) {
                    if ((rgb  & 0xFFFFFF) == sourceColor[i]) {
                        if (targetColor[i] != 0x00000000) {
                            rgb = new Color(targetColor[i]).getRGB();
                        } else {
                            isTransparency = true;
                        }
                    }
                }
                if (!isTransparency) {
                    bufferedImage.setRGB(x, y, rgb);
                }
            }
        }
       return bufferedImage;
    }

    static int xOfIndex(int index) {
        return 17 * index;
    }
    static int drawXOfIndex(int index) {
        return WIDTH * index;
    }

    public static void main(String[] args) {
//        添加管道相关
//        getPipeAboutBlock(g);
//        普通模块
//        getNormalBlock(g);
//         背景
//        getBackground(g);

        Consumer<Graphics> handler = TextureJFrame::getEnemies;
        if (args.length == 1 && args[0].equals("--debug")) {
            runDebug(handler);
        } else {
            outputImage(3, 1, handler);
        }
    }


    private static void getEnemies(Graphics g) {
        int size = WIDTH;
        g.drawImage(enemies.getSubimage(0,16, 16,16), 0, 0, size,size,null);
        g.drawImage(enemies.getSubimage(2 + 16,16, 16,16), size, 0, size,size,null);
        g.drawImage(enemies.getSubimage(4 + 16 * 2,16, 16,16), size * 2, 0, size,size,null);
    }


    private static void getMario(Graphics g) {

        int size = WIDTH;

        g.drawImage(marios.getSubimage(0,8, 16,16), 0, 0, size,size,null);
        g.drawImage(marios.getSubimage(4 + 16,8, 16,16), size, 0, size,size,null);
        g.drawImage(marios.getSubimage(4 + 16 * 2 + 2,8, 16,16), size * 2, 0, size,size,null);
        g.drawImage(marios.getSubimage(4 + 16 * 3 + 2 + 2,8, 16,16), size * 3, 0, size,size,null);
        g.drawImage(marios.getSubimage(4 * 2 + 16 * 4 + 2 + 2,8, 16,16), size * 4, 0, size,size,null);
        g.drawImage(marios.getSubimage(4 * 3 + 16 * 5+ 2 + 2,8, 16,16), size * 5, 0,  size,size,null);
        g.drawImage(marios.getSubimage(4 * 4 + 16 * 6+ 2 + 2,8, 16,16), size * 6, 0,  size,size,null);

        int startX = 4 * 5 + 16 * 7+ 2 + 2 ;

        g.drawImage(marios.getSubimage(startX,8, 16,16), size * 7, 0, size,size,null);
        g.drawImage(marios.getSubimage(startX + 2 + 16,8, 16,16), size * 8, 0, size,size,null);
        g.drawImage(marios.getSubimage(startX + 2 + 16 * 2 + 4,8, 16,16), size * 9, 0, size,size,null);
        g.drawImage(marios.getSubimage(startX + 2 * 2 + 16 * 3 + 4,8, 16,16), size * 10, 0, size,size,null);
        g.drawImage(marios.getSubimage(startX + 2 * 3 + 16 * 4 + 4,8, 16,16), size * 11, 0, size,size,null);
        g.drawImage(marios.getSubimage(startX + 2 * 4 + 16 * 5 + 4,8, 16,16), size * 12, 0,  size,size,null);
        g.drawImage(marios.getSubimage(startX + 2 * 5 + 16 * 6 + 4,8, 16,16), size * 13, 0,  size,size,null);


        g.drawImage(marios.getSubimage(0,8 * 2 + 16, 16,32), 0, size, size,size * 2,null);
        g.drawImage(marios.getSubimage(4 + 16,8 * 2 + 16, 16,32), size, size , size,size * 2,null);
        g.drawImage(marios.getSubimage(4 + 16 * 2 + 2,8 * 2 + 16, 16,32), size * 2, size , size,size * 2,null);
        g.drawImage(marios.getSubimage(4 + 16 * 3 + 2 + 2,8 * 2 + 16, 16,32), size *3, size , size,size * 2,null);
        g.drawImage(marios.getSubimage(4 * 2 + 16 * 4 + 2 + 2,8 * 2 + 16, 16,32), size *4, size, size,size * 2,null);
        g.drawImage(marios.getSubimage(4 * 3 + 16 * 5+ 2 + 2,8 * 2 + 16, 16,32), size * 5, size , size,size * 2,null);
        g.drawImage(marios.getSubimage(4 * 4 + 16 * 6+ 2 + 2,8 * 2 + 16, 16,32), size *6, size , size,size * 2,null);


        g.drawImage(marios.getSubimage(startX,8 * 2 + 16, 16,32), size * 7, size, size,size * 2,null);
        g.drawImage(marios.getSubimage(startX + 2 + 16,8 * 2 + 16, 16,32), size * 8, size, size,size * 2,null);
        g.drawImage(marios.getSubimage(startX + 2 + 16 * 2 + 4,8 * 2 + 16, 16,32), size * 9, size, size,size * 2,null);
        g.drawImage(marios.getSubimage(startX + 2 * 2 + 16 * 3 + 4,8 * 2 + 16, 16,32), size * 10, size, size,size * 2,null);
        g.drawImage(marios.getSubimage(startX + 2 * 3 + 16 * 4 + 4,8 * 2 + 16, 16,32), size * 11, size, size,size * 2,null);
        g.drawImage(marios.getSubimage(startX + 2 * 4 + 16 * 5 + 4,8 * 2 + 16, 16,32), size * 12, size,  size,size * 2,null);
        g.drawImage(marios.getSubimage(startX + 2 * 5 + 16 * 6 + 4,8 * 2 + 16, 16,32), size * 13, size,  size,size * 2,null);

    }


    private static void runDebug(Consumer<Graphics> handler ) {
        JFrame jFrame = new JFrame();
        jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jFrame.setSize(800, 600);
        jFrame.setLocationRelativeTo(null);
        jFrame.add(new TextureJFrame(handler));
        jFrame.setVisible(true);
    }
}
